/*
* =====================================================================================
*
*       Filename:  stack.c
*
*    Description:  
*
*        Version:  1.0
*        Created:  2010年09月18日 11时09分22秒
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  YOUR NAME (), 
*        Company:  
*
* =====================================================================================
*/

#include "me/stack.h"
#include "me/mem.h"
#define DEFULTINITSIZE 16 
#define STEP 2

except_t PopEmptyStack_Failed = {
	"PopEmptyStack_Failed",
	"Reach the base of this stack, unable to pop.",
};





struct stack_s {
	size_t size;
	void **base;
	void **top;
};

void *
stack_gettop(stack_t s)
{
	if (stack_isempty(s))
		RAISE(PopEmptyStack_Failed);
	return *s->top;
}

stack_t 
stack_new(size_t initsize)
{
	stack_t s;

	initsize = initsize ? initsize : DEFULTINITSIZE;
	s = NEW(s);
	s->base = ALLOC(sizeof(void*) * initsize);
	s->size = initsize;
	s->top = s->base;
	return s;
}

void 
stack_push(stack_t s, void *elem)
{
	size_t space = s->top - s->base;
	if ( space == s->size - 1) {
		s->base = REALLOC(s->base, s->size*STEP*sizeof(void*));	
		s->top = s->base + space;
		s->size *= STEP;
	}
	*++s->top = elem;
}

// 错误处理未完
void *
stack_pop(stack_t s)
{
	if (stack_isempty(s)) {
		RAISE( PopEmptyStack_Failed );
	}
	return *s->top--;
}

void
stack_destroy(stack_t *sp)
{
	stack_t s = *sp;
	FREE(s->base);
	FREE(s);
	*sp = NULL;
}


inline bool 
stack_isempty(stack_t s)
{
	return s->top == s->base;
}


